# Copyright (C) 2007 Laszlo Pandy <laszlok2@gmail.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.

import gtk
import gobject
import datetime
Date = datetime.date

from AdventureMoney.core import Utils
import InterfaceUtils

class CalendarPopupWindow:
	def __init__(self, closeCb, changeCb):
		self.wTree = InterfaceUtils.GetGladeTree("CalendarPopup")
		
		self.wTree.signal_autoconnect({
			"OnCalendarDeleteEvent"	: self.OnHideCalendar,
			"OnCalendarDoubleClick"	: self.OnDoubleClick,
			"OnCalendarDaySelected"	: self.OnDateSelection,
			"OnCalendarKeyPress"	: self.OnKeyPress,
			"OnClose"		: self.OnHideCalendar
		})
		
		self.window = self.wTree.get_widget("CalendarPopup")
		self.calendar = self.wTree.get_widget("CalendarPopupWidget")
		self.closeCb = closeCb
		self.changeCb = changeCb
		
	def OnKeyPress(self, widget, event):
		key = gtk.gdk.keyval_name(event.keyval)
		
		if key == "Escape" or key == "Return":
			self.OnHideCalendar()
			return True
		
	def OnDateSelection(self, widget):
		self.changeCb()
		
	def OnDoubleClick(self, widget):
		self.OnHideCalendar()
		
	def OnHideCalendar(self, widget=None):
		self.window.hide()
		self.window.grab_remove()
		self.closeCb()
		return True


class CalendarEntry(gtk.HBox):
	
	__gtype_name__ = 'CalendarEntry'
	
	def __init__(self, dateTuple=None):
		gtk.HBox.__init__(self)
		
		self.dateEntry = gtk.Entry()
		self.calendarButton = gtk.Button()
		self.pack_start(self.dateEntry)
		self.pack_start(self.calendarButton, False)
		
		self.buttonHBox = gtk.HBox()
		self.calendarButton.add(self.buttonHBox)
		self.calendarButton.connect("clicked", self.OnCalendar)
		
		self.arrow = gtk.Arrow(gtk.ARROW_DOWN, gtk.SHADOW_OUT)
		self.buttonHBox.pack_start(self.arrow)
		
		self.label = gtk.Label("Calendar")
		self.label.set_padding(2, 0)
		self.buttonHBox.pack_start(self.label)
		
		self.calendarPopup = CalendarPopupWindow(self.OnCalendarClose, self.OnCalendarChange)
		#self.calendarPopup.window.set_transient_for(self.window)
		if dateTuple:
			self.dateEntry.set_text(str( Date(*dateTuple) ))
		
	def OnCalendar(self, widget):
		#/* Temporarily grab pointer and keyboard on a window we know exists; we
		#+ * do this so that the grab (with owner events == TRUE) affects
		#+ * events generated when the window is mapped, such as enter
		#+ * notify events on subwidgets. If the grab fails, bail out.
		#+ */
		if not self.popup_grab_on_window(widget.window, gtk.get_current_event_time ()):
			return
	
		(dlgWidth, dlgHeight) = self.calendarPopup.window.size_request()
	
		(x, y) = self.calendarButton.window.get_origin()
		
		alloc = self.calendarButton.get_allocation()
		x += alloc.x + alloc.width - dlgWidth
		y += alloc.y + alloc.height
	
		x = max(x, 0)
		y = max(y, 0)
	
		self.calendarPopup.window.move(x, y)
	
		self.calendarPopup.window.grab_add()
		self.calendarPopup.window.show()
		self.calendarPopup.calendar.grab_focus()
	
		#/* Now transfer our grabs to the popup window; this
		#* should always succeed.
		#*/
		self.popup_grab_on_window (self.calendarPopup.window.window, gtk.get_current_event_time ())
		
	def OnCalendarClose(self):
		self.OnCalendarChange()
		
	def OnCalendarChange(self):
		(year, month, day) = self.calendarPopup.calendar.get_date()
		month += 1
		string = str( Date(year, month, day) )
		self.dateEntry.set_text(string)
		
		self.emit("date_changed")
		
	def popup_grab_on_window(self, window, activate_time):
		response = gtk.gdk.pointer_grab(window, True,
				gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK |
				gtk.gdk.POINTER_MOTION_MASK,
				None, None, activate_time)
		
		if response == gtk.gdk.GRAB_SUCCESS:
			response = gtk.gdk.keyboard_grab (window, True, activate_time)
			if response == gtk.gdk.GRAB_SUCCESS:
				return True
		else:
			gtk.gdk.pointer_ungrab(activate_time)
			return False
		return False
	
	def set_text(self, text):
		self.dateEntry.set_text(text)
		
	def get_text(self):
		return self.dateEntry.get_text()
	
gobject.signal_new(
	"date_changed",
	CalendarEntry,
	gobject.SIGNAL_RUN_FIRST,
	gobject.TYPE_NONE,
	()
)
